package com.example.graduation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.graduation.entity.*;
import com.example.graduation.exception.MyException;
import com.example.graduation.form.IdForm;
import com.example.graduation.mapper.*;
import com.example.graduation.service.GoodsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.graduation.service.HotService;
import com.example.graduation.service.RecordsService;
import com.example.graduation.util.JwtUtil;
import com.example.graduation.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Consumer;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xyc
 * @since 2022-02-11
 */
@Slf4j
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements GoodsService {


    @Resource
    private GoodsMapper goodsMapper;


    @Resource
    private HotService hotService;

    @Resource
    private RecordsService recordsService;


    @Resource
    private NoticeMapper noticeMapper;

    @Resource
    private JwtUtil jwtUtil;

    @Resource
    private ShopMapper shopMapper;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private ShoppingCartMapper shoppingCartMapper;


    /**
     * 根据商品id，和商店id查询商品信息
     * 因为每一个商品需要归属于一家商店
     *
     * @param goodsId
     * @return {@link Goods}
     * @author xieyucan
     * CreateDate 2022/3/20 21:13
     */
    @Override
    public Goods findGoodsById(Integer goodsId, Integer shopId, String token) {
        if (goodsId == null || shopId == null) {
            throw new MyException("查询失败");
        }
        try {
            QueryWrapper<Goods> wrapper = new QueryWrapper<>();
            wrapper.eq("goods_id", goodsId).eq("shop_id", shopId);
            Goods goods = goodsMapper.selectOne(wrapper);
            if (goods != null) {
                /**
                 * 当用户在查询商品信息的时候，我们在这里默认就是热搜次数+1
                 */

                hotService.updateHot(goods.getGoodsId(), goods.getGoodsname());
                /**
                 * 在这里添加用户足迹
                 */
                recordsService.insertUpdate(token, goodsId);
                return goods;
            } else {
                throw new MyException("查询失败");
            }
        } catch (Exception e) {
            log.error("查询失败");
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }


    /**
     * 搜索商品，当status为1的时候，搜索的内容为搜索框的内容，对此，查询的是商品的名称
     * 当status为2的时候，搜索的内容为商品类型，对此搜索的字段是type
     *
     * @param type
     * @param page
     * @param size
     * @param status
     * @return {@link List< Goods>}
     * @author xieyucan
     * CreateDate 2022/3/22 9:43
     */
    @Override
    public Page<Goods> findGoodsByType(String type, Integer page,
                                       Integer size, Integer status) {
        //页数
        if (page == null) {
            page = 1;
        }
        //条数
        if (size == null) {
            size = 8;
        }
        try {
            QueryWrapper<Goods> wrapper = new QueryWrapper<>();
            //判断
            if (status == 1) {
                wrapper.eq("goods_name", type);
                Page<Goods> goodsPage = goodsMapper.selectPage(
                        new Page<>(page, size), wrapper);
                return goodsPage;
            } else if (status == 2) {
                wrapper.eq("type", type);
                Page<Goods> goodsPage = goodsMapper.selectPage(
                        new Page<>(page, size), wrapper);
                return goodsPage;
            } else {
                throw new MyException("不存在该查询类型");
            }
        } catch (Exception e) {
            log.error("查询失败");
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }


    /**
     * 搜索商品，当status为1的时候，搜索的内容为搜索框的内容，对此，查询的是商品的名称
     * 当status为2的时候，搜索的内容为商品类型，对此搜索的字段是type,并且设定最高商品价格
     *
     * @param type
     * @param price
     * @param page
     * @param size
     * @return {@link Page< Goods>}
     * @author xieyucan
     * CreateDate 2022/3/22 9:55
     */
    @Override
    public Page<Goods> findGoodsByPriceLow(String type, Double price, Integer page, Integer size, Integer status) {
        if (page == null) {
            page = 1;
        }
        if (size == null) {
            size = 8;
        }
        try {
            QueryWrapper<Goods> wrapper = new QueryWrapper<>();
            if (status == 1) {
                wrapper.eq("goods_name", type).le("new_price", price);
                Page<Goods> goodsPage = goodsMapper.selectPage(new Page<>(page, size), wrapper);
                return goodsPage;
            } else if (status == 2) {
                wrapper.eq("type", type).le("new_price", price);
                Page<Goods> goodsPage = goodsMapper.selectPage(new Page<>(page, size), wrapper);
                return goodsPage;
            } else {
                throw new MyException("不存在该查询类型");
            }
        } catch (Exception e) {
            log.error("查询失败");
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }


    /**
     * 搜索商品，当status为1的时候，搜索的内容为搜索框的内容，对此，查询的是商品的名称
     * 当status为2的时候，搜索的内容为商品类型，对此搜索的字段是type,并且设定商品价格区间
     *
     * @param type
     * @param lowPrice
     * @param highPrice
     * @param page
     * @param size
     * @param status
     * @return {@link Page< Goods>}
     * @author xieyucan
     * CreateDate 2022/3/22 10:18
     */
    @Override
    public Page<Goods> findGoodsByPriceBetween(String type, Double lowPrice, Double highPrice, Integer page, Integer size, Integer status) {
        if (page == null) {
            page = 1;
        }
        if (size == null) {
            size = 8;
        }
        try {
            QueryWrapper<Goods> wrapper = new QueryWrapper<>();
            if (status == 1) {
                wrapper.eq("goods_name", type)
                        .and((Consumer<QueryWrapper<Goods>>) wrapper.le("new_price", highPrice).ge("new_price", lowPrice));
                Page<Goods> goodsPage = goodsMapper.selectPage(new Page<>(page, size), wrapper);
                return goodsPage;
            } else if (status == 2) {
                wrapper.eq("type", type).le("new_price", highPrice)
                        .and((Consumer<QueryWrapper<Goods>>) wrapper.le("new_price", highPrice).ge("new_price", lowPrice));
                Page<Goods> goodsPage = goodsMapper.selectPage(new Page<>(page, size), wrapper);
                return goodsPage;
            } else {
                throw new MyException("不存在该查询类型");
            }
        } catch (Exception e) {
            log.error("查询失败");
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }


    /**
     * 搜索商品，当status为1的时候，搜索的内容为搜索框的内容，对此，查询的是商品的名称
     * 当status为2的时候，搜索的内容为商品类型，对此搜索的字段是type,并且设定status1为商品销量的标签，
     * status1==1的时候，表示销量从高到低，status1==2的时候，表示销量从低到高
     *
     * @param type
     * @param sale
     * @param page
     * @param size
     * @param status
     * @return {@link Page< Goods>}
     * @author xieyucan
     * CreateDate 2022/3/22 10:18
     */
    @Override
    public Page<Goods> findGoodsBySale(String type, Integer sale,
                                       Integer page, Integer size,
                                       Integer status, Integer status1) {
        if (page == null) {
            page = 1;
        }
        if (size == null) {
            size = 8;
        }
        try {
            QueryWrapper<Goods> wrapper = new QueryWrapper<>();
            if (status == 1) {
                //status1==1的时候，表示销量从高到低
                if (status1 == 1) {
                    wrapper.eq("goods_name", type).
                            orderByDesc("sale", String.valueOf(sale));
                    Page<Goods> goodsPage = goodsMapper.selectPage(new Page<>(page, size),
                            wrapper);
                    return goodsPage;
                    //status1==2的时候，表示销量从低到高
                } else if (status1 == 2) {
                    wrapper.eq("goods_name", type).
                            orderByAsc("sale", String.valueOf(sale));
                    Page<Goods> goodsPage = goodsMapper.selectPage(new Page<>(page, size),
                            wrapper);
                    return goodsPage;
                } else {
                    throw new MyException("查询失败");
                }
            } else if (status == 2) {
                if (status1 == 1) {
                    wrapper.eq("type", type).orderByDesc("sale",
                            String.valueOf(sale));
                    Page<Goods> goodsPage = goodsMapper.selectPage(new Page<>
                            (page, size), wrapper);
                    return goodsPage;
                } else if (status1 == 2) {
                    wrapper.eq("type", type).orderByAsc("sale",
                            String.valueOf(sale));
                    Page<Goods> goodsPage = goodsMapper.selectPage(new Page<>
                            (page, size), wrapper);
                    return goodsPage;
                } else {
                    throw new MyException("查询失败");
                }
            } else {
                throw new MyException("不存在该查询类型");
            }
        } catch (Exception e) {
            log.error("查询失败");
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }


    /**
     * 这个接口主要描述申请秒杀的功能，当申请成功，将其存放到缓存中即可
     *
     * @param
     * @return
     */
    public Boolean applyMiaoSha(String token, Integer goodsId) {
        try {
            int userId = jwtUtil.getUserIdByToken(token);
            //Goods goods = goodsMapper.selectById(goodsId);
            Notice notice = new Notice();
            notice.builder()
                    .sendid(userId)
                    .acceptid(17)
                    .content("秒杀申请")
                    .createtime(System.currentTimeMillis() / 1000)
                    .goodsId(goodsId)
                    .build();

            int insert = noticeMapper.insert(notice);
            return true;
        } catch (Exception e) {
            throw new RuntimeException("操作异常");
        }
    }


    /**
     * 上架商品
     *
     * @param goods
     * @param token
     * @return
     */
    public Boolean addGoods(Goods goods, String token) {

        int userId = jwtUtil.getUserIdByToken(token);
        goods.setUserId(userId);
        QueryWrapper<Shop> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        Shop shop = shopMapper.selectOne(wrapper);
        goods.setShopId(shop.getShopId());
        Calendar calendar = Calendar.getInstance();
        goods.setMonth(calendar.get(Calendar.MONTH) + 1);
        goods.setCreateTime(System.currentTimeMillis());
        goodsMapper.insert(goods);
        return true;

    }


    /**
     * 删除商品
     *
     * @param token
     * @param goodsId
     * @return
     */
    public Boolean deleteGoods(String token, Integer goodsId) {
        try {
            Integer userId = jwtUtil.getUserIdByToken(token);
            Goods goods = goodsMapper.selectById(goodsId);
            Integer userId1 = goods.getUserId();
            if (userId == userId1) {
                goodsMapper.deleteById(goodsId);
                return true;
            }
            return false;
        } catch (Exception e) {
            throw new RuntimeException("没有相关权限");
        }
    }


    public Page<Goods> finggoodsByToken(String token, Integer page, Integer size) {
        if (page == null) {
            page = 1;
        }
        if (size == null) {
            size = 4;
        }
        int userId = jwtUtil.getUserIdByToken(token);
        QueryWrapper<Goods> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        Page<Goods> goodsPage = goodsMapper.selectPage(new Page<>(page, size), wrapper);
        return goodsPage;
    }


    public Set<String> findallType(String token) {
        int userId = jwtUtil.getUserIdByToken(token);
        QueryWrapper<Goods> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        List<Goods> list = goodsMapper.selectList(wrapper);
        Set<String> set = new HashSet<>();
        for (Goods goods : list) {
            if (!set.contains(goods.getType())) {
                set.add(goods.getType());
            }
        }
        return set;
    }


    /**
     * 根据店铺id查询店铺商品类型
     *
     * @param
     * @return
     */
    public Set<String> findallTypeById(Integer shopId) {
        QueryWrapper<Goods> wrapper = new QueryWrapper<>();
        wrapper.eq("shop_id", shopId);
        List<Goods> list = goodsMapper.selectList(wrapper);
        Set<String> set = new HashSet<>();
        for (Goods goods : list) {
            if (!set.contains(goods.getType())) {
                set.add(goods.getType());
            }
        }
        return set;
    }


    public Page<Goods> finggoodsByshopId(Integer shopId, Integer page, Integer size) {
        if (page == null) {
            page = 1;
        }
        if (size == null) {
            size = 4;
        }
        QueryWrapper<Goods> wrapper = new QueryWrapper<>();
        wrapper.eq("shop_id", shopId);
        Page<Goods> goodsPage = goodsMapper.selectPage(new Page<>(page, size), wrapper);
        return goodsPage;
    }

    public List<Goods> likegoods(String name) {
        try {
            QueryWrapper<Goods> wrapper = new QueryWrapper<>();
            wrapper.like("goodsname", name);
            List<Goods> list = goodsMapper.selectList(wrapper);
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }

    }

    public Goods changeGoods(Goods goods) {
        Integer goodsId = goods.getGoodsId();
        QueryWrapper<Goods> wrapper = new QueryWrapper<>();
        wrapper.eq("goods_id", goodsId);
        int update = goodsMapper.update(goods, wrapper);
        return goods;
    }


    public Goods selectByid(Integer id) {

        QueryWrapper<Goods> wrapper = new QueryWrapper<>();
        wrapper.eq("goods_id", id);
        Goods goods = goodsMapper.selectOne(wrapper);
        return goods;
    }


    /**
     * 申请秒杀
     *
     * @param token
     * @param name
     * @param count
     * @param time
     * @param content
     */
    public void miaosha(String token, String name, Integer count, Long time, String content) {
        try {
            int userId = jwtUtil.getUserIdByToken(token);
            QueryWrapper<Shop> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id", userId);
            Shop shop = shopMapper.selectOne(wrapper);
            QueryWrapper<Goods> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("goodsname", name).eq("shop_id", shop.getShopId());
            Goods goods = goodsMapper.selectOne(queryWrapper);
            String key = "miaoSha" + goods.getGoodsId();
            redisTemplate.opsForValue().set(key, count);
            Notice notice = new Notice();
            notice.setStatus(0);
            notice.setGoodsId(goods.getGoodsId());
            notice.setType(3);
            notice.setSendid(userId);
            notice.setAcceptid(17);
            notice.setContent(content);
            notice.setNum(count);
            notice.setCreatetime(time);
            noticeMapper.insert(notice);
        } catch (Exception e) {

        }

    }


    /**
     * 查找秒杀商品
     *
     * @param type
     * @return
     */
    public List<Goods> findallg(Integer type) {
        QueryWrapper<Notice> wrapper = new QueryWrapper<>();
        wrapper.eq("type", type);
        List<Notice> notices = noticeMapper.selectList(wrapper);
        List<Goods> list = new ArrayList<>();
        for (Notice notice : notices) {
            QueryWrapper<Goods> goodsQueryWrapper = new QueryWrapper<>();
            goodsQueryWrapper.eq("goods_id", notice.getGoodsId());
            Goods goods = goodsMapper.selectOne(goodsQueryWrapper);
            list.add(goods);
        }
        return list;
    }


    /**
     * 购买秒杀商品
     *
     * @param token
     * @param goodsId
     * @return
     */
    public Boolean buyMiaoShaGoods(String token, Integer goodsId) {
        try {
            int userId = jwtUtil.getUserIdByToken(token);
            String key = "miaoSha" + goodsId;
            //获取秒杀商品的库存
            Integer count = (Integer) redisTemplate.opsForValue().get(key);
            if (count > 0) {
                String redisKey = token + goodsId;
                RedisAtomicLong redisAtomicLong = new RedisAtomicLong(redisKey,
                        redisTemplate.getConnectionFactory());
                redisAtomicLong.getAndAdd(1);
                //当用户事第一次抢购，我们就放行
                if (redisAtomicLong.get() == 1) {
                    Goods goods = goodsMapper.selectById(goodsId);
                    //为用户订单列表添加数据
                    Torder torder = new Torder();
                    long orderId = System.currentTimeMillis();
                    torder.setOrderId(orderId);
                    torder.setShopId(goods.getShopId());
                    torder.setUserId(userId);
                    torder.setStatus(2);
                    torder.setCreateTime(orderId);
                    torder.setTotal(goods.getNewprice());
                    orderMapper.insert(torder);
                    ShoppingCart shoppingCart = new ShoppingCart();
                    shoppingCart.setUserId(userId);
                    shoppingCart.setGoodsId(goodsId);
                    shoppingCart.setOldPrice(goods.getNewprice());
                    shoppingCart.setOrderId(orderId);
                    shoppingCart.setShopId(goods.getShopId());
                    shoppingCart.setCreateTime(orderId);
                    shoppingCart.setStatus(0);
                    shoppingCart.setCou(count);
                    shoppingCartMapper.insert(shoppingCart);
                    redisTemplate.opsForValue().decrement(key, 1);
                    return true;
                } else {
                    throw new MyException("该商品只能抢购一次~");
                }
            } else {
                throw new MyException("该商品已被抢购完了~");
            }
        } catch (Exception e) {
            throw new MyException(e.getMessage());
        }
    }

}
